package com.yvon.boot.mybatis.utils;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.yvon.boot.mybatis.page.SearchCriteria;
import com.yvon.boot.mybatis.page.SearchParam;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : Yvon
 * @since : 2021-09-03
 */
public class SearchUtils {

    public static SearchParam getParam(SearchCriteria searchCriteria, String fieldName) {
        Set<SearchParam> searchParams = searchCriteria.getSearchParams();
        if (CollectionUtils.isEmpty(searchParams)) {
            return null;
        }
        return searchParams.stream()
                .filter(searchParam -> fieldName.equals(searchParam.getFieldName()))
                .findFirst().orElse(null);
    }

    public static String popParam(SearchCriteria searchCriteria, String fieldName) {
        Set<SearchParam> searchParams = searchCriteria.getSearchParams();
        SearchParam param = getParam(searchCriteria, fieldName);
        if (Objects.nonNull(param)) {
            searchParams.remove(param);
            searchCriteria.setSearchParams(searchParams);
            return param.getValue();
        }
        return null;
    }

    public static void pushParam(SearchCriteria searchCriteria, String fieldName, String value) {
       searchCriteria.addSearchParam(SearchParam.builder()
               .fieldName(fieldName)
               .operate(SearchParam.Operator.eq)
               .value(value).build());
    }

    public static void pushParam(SearchCriteria searchCriteria, String fieldName, Collection<? extends Serializable> value) {
        searchCriteria.addSearchParam(SearchParam.builder()
                .fieldName(fieldName)
                .operate(SearchParam.Operator.in)
                .build());
    }

    /**
     * 修改分页查询请求参数
     *
     * <p>
     *     分页查询的条件，有的参数可能需要在其他关联表中取出来
     * </p>
     *
     * @param searchCriteria 搜索条件
     * @param fieldName      字段名（前端传进来的字段名）
     * @param column         列名（实际需要在数据库中查询的字段名）
     * @param function       函数（提供实际查询值的方法）
     * @return void
     * @author : Yvon / 2021-09-27
     */
    public static void pushParam(SearchCriteria searchCriteria, String fieldName, String column, Function<List, List> function) {
        String values = popParam(searchCriteria, fieldName);
        if (Objects.nonNull(values) && !"".equals(values)) {
            List<String> valueList = stringToList(values, ",");
            List<? extends Serializable> apply = function.apply(valueList);
            if (!CollectionUtils.isEmpty(apply)) {
                String value = apply.stream().map(String::valueOf).collect(Collectors.joining(","));
                searchCriteria.addSearchParam(SearchParam.builder()
                        .fieldName(column)
                        .operate(SearchParam.Operator.in)
                        .value(value).build());
            }
        }
    }




    public static String getValue(SearchCriteria searchCriteria, String fieldName) {
        SearchParam param = getParam(searchCriteria, fieldName);
        return Objects.nonNull(param) ? param.getValue() : null;
    }

    private static List<String> stringToList(@NonNull String toSplit, @Nullable String delimiter) {
        if (Strings.isNullOrEmpty(toSplit)) {
            throw new IllegalArgumentException("toSplit can not be null or empty!");
        } else {
            if (Strings.isNullOrEmpty(delimiter)) {
                delimiter = ",";
            }

            ArrayList searchValue;
            if (!toSplit.contains(delimiter)) {
                searchValue = Lists.newArrayList(new String[]{toSplit});
            } else {
                searchValue = Lists.newArrayList(Lists.newArrayList(toSplit.split(delimiter)));
            }

            return searchValue;
        }
    }
}
